
/*!
 * \file      nextshapemanager.cpp
 * \brief     NextShapeManager implementation.
 * \author    Duriez Franck
 * \author    Carton Paul-Henri
 * \version   0.1
 */

#include "nextshapemanager.h"
#include "coloredshape.h"
#include "basicimageshape.h"
#include "crazycoloredshape.h"
#include "mixshape.h"
#include "constant.h"

NextShapeManager::NextShapeManager(QSFMLWidget *displayer, float *dt) : /*{{{*/
		Drawable(displayer, displayer, dt),
		m_next_shape(NULL),
		m_background(sf::Shape::Rectangle(0, 0,
					SHAPE_BACKGROUND_SIZE_NEXT,
					SHAPE_BACKGROUND_SIZE_NEXT,
					SHAPE_BACKGROUND_COLOR_NEXT,
					OUTLINE,
					OUTLINE_COLOR))
{
	// On creation it's needed to fill the next Shape pointer
	createShape();

	// The background is set in the right place here
	setPosition(Vector2f(SHAPE_BACKGROUND_POS_X_NEXT,
			SHAPE_BACKGROUND_POS_Y_NEXT));
} /*}}}*/

NextShapeManager::~NextShapeManager() /*{{{*/
{
} /*}}}*/

void NextShapeManager::createShape() throw(TetrisException::UnexpectedShape) /*{{{*/
{
	// To avoid memory leak, we need to be sure that no
	// Shape is present in the pointer.
	ASSERT(!m_next_shape,"","Already a Shape in the NextShapeManager");

	if (m_next_shape) throw TetrisException::UnexpectedShape(
			"Can't create Shape because the NextShapeManager is not empty !");

	// Random number for the Shape choice
	int rand = sf::Randomizer::Random(0,3);

	// For the moment we choose to set a new Shape randomly
	// among all the example Shapes that we have implemented.
	switch (rand) {
	case 0 :
		m_next_shape = new ColoredShape(displayer, displayer, dt);
		break;
	case 1 :
		m_next_shape = new BasicImageShape(displayer, displayer, dt);
		break;
	case 2 :
		m_next_shape = new CrazyColoredShape(displayer, displayer, dt);
		break;
	case 3 :
		m_next_shape = new MixShape(displayer, displayer, dt);
		break;
	}

	// The ShapeType is set randomly too.
	m_next_shape->setRandomShapeType();

	// The shape newly created is set in the right place of the
	// graphical part of the NextShapeManager.
	/// \todo This is not sufficient, because it doesn't
	///       take in count the NextShapeManager::m_position
	///       and so is not stable by position changement.
	m_next_shape->setPosition(Vector2f(
				SHAPE_POS_X_NEXT,
				SHAPE_POS_Y_NEXT));
} /*}}}*/

Shape* NextShapeManager::transfertShape() /*{{{*/
{
	// Here the previous "next Shape" is stocked
	// to avoid pointer loosing
	Shape* tmp = m_next_shape;

	// symbolic rotation
	int dir = (int) (tmp->getRotation() / 90.f);
	tmp->m_current_orientation = (Shape::Direction) dir;
	tmp->setRotation(dir * 90.f);
	tmp->rotateInContainer((unsigned int) dir);

	// next shape creation
	m_next_shape = NULL;
	createShape();

	// previous "next shape is returned
	return tmp;
} /*}}}*/

/************
 * DRAWABLE *
 ************/
/*{{{*/
void NextShapeManager::draw() const /*{{{*/
{
	// Background is drawn first
	displayer->Draw(m_background);

	// And then the stocked next shape if exists
	if (m_next_shape) m_next_shape->draw();
	
} /*}}}*/

void NextShapeManager::update() /*{{{*/
{
	// test next shape not empty
	if (m_next_shape)
	{
		// rotate the graphic part of the Shape
		m_next_shape->rotate(SHAPE_ROTATION_SPEED * (*dt));

		// and now update it
		m_next_shape->update();
	}
	else
	{
		DEBUGGER("there isn't next shape");
	}
} /*}}}*/

void NextShapeManager::setCenter(Vector2f) /*{{{*/
{
	// Not implemented for the moment
	/// \todo Implement it.
} /*}}}*/

void NextShapeManager::setPosition(Vector2f position) /*{{{*/
{
	// easy to understand
	m_position = position;
	m_background.SetPosition(m_position);
} /*}}}*/

void NextShapeManager::setRotation(float) /*{{{*/
{
	// Not implemented for the moment
	/// \todo Implement it.
} /*}}}*/

void NextShapeManager::moveCenter(Vector2f) /*{{{*/
{
	// Not implemented for the moment
	/// \todo Implement it.
} /*}}}*/

void NextShapeManager::move(Vector2f) /*{{{*/
{
	// Not implemented for the moment
	/// \todo Implement it.
} /*}}}*/

void NextShapeManager::rotate(float) /*{{{*/
{
	// Not implemented for the moment
	/// \todo Implement it.
} /*}}}*/

Vector2f NextShapeManager::getCenter() const /*{{{*/
{
	// easy to understand
	return m_position + Vector2f(SHAPE_BACKGROUND_SIZE_NEXT/2, SHAPE_BACKGROUND_SIZE_NEXT/2);
} /*}}}*/

Vector2f NextShapeManager::getPosition() const /*{{{*/
{
	return m_position;
} /*}}}*/

float NextShapeManager::getRotation() const /*{{{*/
{
	// Not implemented for the moment
	/// \todo Implement it.
	return 0.f;
} /*}}}*/

std::string NextShapeManager::toString() const /*{{{*/
{
	// Not implemented for the moment
	/// \todo Implement it.
	return std::string();
} /*}}}*/
/*}}}*/

